package com.api.shop.util.redis;

import com.api.shop.exception.ParamException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class RedisUtil {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     *  指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return 操作结果
     */
    public boolean expire(String key, long time){
        try {
            if(time > 0){
                stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        }catch (Exception e){
            log.error("Redis expire error: {}", e.getMessage());
            return false;
        }
    }

    /**
     *  根据 key 获取过期时间
     * @param key 键 不能为 null
     * @return 时间(秒); 0: 永久有效
     */
    public long getExpire(String key){
        return stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     *  判断 key 是否存在
     * @param key 键
     * @return true: 存在; false: 不存在
     */
    public boolean hasKey(String key){
        try {
            return stringRedisTemplate.hasKey(key);
        }catch (Exception e){
            log.error("Redis getExpire error: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 删除缓存
     * @param keys 键
     */
    public void delete(String... keys){
        if(keys != null && keys.length > 0){
            if(keys.length == 1){
                stringRedisTemplate.delete(keys[0]);
            }else{
                Collection<String> collection = Arrays.asList(keys);
                stringRedisTemplate.delete(collection);
            }
        }
    }

    public Object get(String key){
        return key == null ? null : stringRedisTemplate.opsForValue().get(key);
    }

    public boolean set(String key, String value){
        try {
            stringRedisTemplate.opsForValue().set(key, value);
            return true;
        }catch (Exception e){
            log.error("RedisString set error: {}", e.getMessage());
            return false;
        }
    }

    public boolean set(String key, String value, long time){
        try {
            if(time > 0){
                stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            }else{
                set(key, value);
            }
            return true;
        }catch (Exception e){
            log.error("RedisString Time set error: {}", e.getMessage());
            return false;
        }
    }

    public Object getHash(String key, String hashKey){
        return key == null ? null : redisTemplate.opsForHash().get(key, hashKey);
    }

    public List getHash(String key){
        return key == null ? null : redisTemplate.opsForHash().values(key);
    }

    public Map<String, Object> entries(String key){
        return redisTemplate.opsForHash().entries(key);
    }

    public boolean setHash(String key, Map<String, Object> map){
        try {
            for(Map.Entry<String, Object> entry : map.entrySet()){
                redisTemplate.opsForHash().put(key, entry.getKey(), entry.getValue());
            }
            return true;
        }catch (Exception e){
            log.error("Redis set error: {}", e.getMessage());
            return false;
        }
    }

    public boolean setHash(String key, String hashKey, Object hashValue){
        try {
            redisTemplate.opsForHash().put(key, hashKey, hashValue);
            return true;
        }catch (Exception e){
            log.error("Redis set error: {}", e.getMessage());
            return false;
        }
    }

    public void deleteHash(String key, String hashKey){
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    /**
     *  递增
     * @param key 键
     * @param delta 要增加的数
     */
    public long incr(String key, long delta){
        if(delta < 0){
            throw new ParamException("递增因子必须大于 0");
        }
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    public long decr(String key, long delta){
        if(delta < 0){
            throw new ParamException("递减因子必须大于 0");
        }
        return stringRedisTemplate.opsForValue().increment(key, -delta);
    }

}
